#include "SaveSystem.h"
#include "LevelManager.h"
#include "EntityManager.h"
#include "../TinyXML/tinyxml.h"
#include <iostream>
#include <sstream>
#include "SGD_String.h"
#include "Rocketeer.h"
#include "Shooter.h"
#include "Shielder.h"
#include "Mech.h"
#include "Helicopter.h"
#include "SinglePlayerState.h"
#include "Level.h"


using namespace std;

CSaveSystem* CSaveSystem::GetInstance( void )
{
	static CSaveSystem s_Instance;

	return &s_Instance;
}

CSaveSystem::CSaveSystem(void)
{

}


CSaveSystem::~CSaveSystem(void)
{

}

void CSaveSystem::WriteOutSlot(int slot, float TimePlayed)
{
	TiXmlDocument doc;

	TiXmlDeclaration* pDecl = new TiXmlDeclaration("1.0", "utf-8", "");
	doc.LinkEndChild(pDecl);

	TiXmlElement* pRoot = new TiXmlElement("Save");
	doc.LinkEndChild(pRoot);

	TiXmlElement* pTime = new TiXmlElement("Time");
	pTime->SetAttribute("time", (int)TimePlayed);
	pRoot->LinkEndChild(pTime);
	

	TiXmlElement* pXYPos1 = new TiXmlElement("Player1");
	pXYPos1->SetAttribute("x", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPlayerShip()->GetPosX());
	pXYPos1->SetAttribute("y", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPlayerShip()->GetPosY());
	pXYPos1->SetAttribute("Health", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPlayerShip()->GetHealth());
	pRoot->LinkEndChild(pXYPos1);
	

	TiXmlElement* pXYPos2 = new TiXmlElement("Player2");
	pXYPos2->SetAttribute("x", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPlayerShip()->GetPosX());
	pXYPos2->SetAttribute("y", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPlayerShip()->GetPosY());
	pXYPos2->SetAttribute("Health", (int)CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPlayerShip()->GetHealth());
	pRoot->LinkEndChild(pXYPos2);
	
	TiXmlElement* pBarricadeNum = new TiXmlElement("Barricade");
	pBarricadeNum->SetAttribute("Size", (int)CEntityManager::GetInstance()->m_Barricades.size());
	pRoot->LinkEndChild(pBarricadeNum);

	for (unsigned int i = 0; i < CEntityManager::GetInstance()->m_Barricades.size(); i++)
	{
		stringstream word;
		word << "Barricade" << i; 
		TiXmlElement* pBarricade = new TiXmlElement(word.str().c_str());
		pBarricade->SetAttribute("Team", (int)CEntityManager::GetInstance()->m_Bases[i]->GetTeam());
		pBarricade->SetAttribute("x", (int)CEntityManager::GetInstance()->m_Barricades[i]->GetPosX());
		pBarricade->SetAttribute("y", (int)CEntityManager::GetInstance()->m_Barricades[i]->GetPosY());
		pBarricade->SetAttribute("Health", (int)CEntityManager::GetInstance()->m_Barricades[i]->GetHealth());
		pRoot->LinkEndChild(pBarricade);

	}

	TiXmlElement* pBaseNum = new TiXmlElement("Base");
	pBaseNum->SetAttribute("Size", (int)CEntityManager::GetInstance()->m_Bases.size());
	pRoot->LinkEndChild(pBaseNum);

	for (unsigned int i = 0; i < CEntityManager::GetInstance()->m_Bases.size(); i++)
	{
		stringstream word;
		word << "Base" << i; 
		TiXmlElement* pBase = new TiXmlElement(word.str().c_str());
		pBase->SetAttribute("Team", (int)CEntityManager::GetInstance()->m_Bases[i]->GetTeam());
		pBase->SetAttribute("x", (int)CEntityManager::GetInstance()->m_Bases[i]->GetPosX());
		pBase->SetAttribute("y", (int)CEntityManager::GetInstance()->m_Bases[i]->GetPosY());
		pBase->SetAttribute("Health", (int)CEntityManager::GetInstance()->m_Bases[i]->GetHealth());
		pRoot->LinkEndChild(pBase);
	}

	TiXmlElement* pCrateNum = new TiXmlElement("Crate");
	pCrateNum->SetAttribute("Size", (int)CEntityManager::GetInstance()->m_Crates.size());
	pRoot->LinkEndChild(pCrateNum);

	for (unsigned int i = 0; i < CEntityManager::GetInstance()->m_Crates.size(); i++)
	{
		stringstream word;
		word << "Crate" << i; 
		TiXmlElement* pCrate = new TiXmlElement(word.str().c_str());
		pCrate->SetAttribute("x", (int)CEntityManager::GetInstance()->m_Bases[i]->GetPosX());
		pCrate->SetAttribute("y", (int)CEntityManager::GetInstance()->m_Bases[i]->GetPosY());
		pRoot->LinkEndChild(pCrate);
	}

	TiXmlElement* pUnitNum = new TiXmlElement("Unit");
	pUnitNum->SetAttribute("Size", (int)CEntityManager::GetInstance()->m_BaseUnits.size());
	pRoot->LinkEndChild(pUnitNum);

	for (unsigned int i = 0; i < CEntityManager::GetInstance()->m_BaseUnits.size(); i++)
	{
		stringstream word;
		word << "Unit" << i; 
		TiXmlElement* pUnit = new TiXmlElement(word.str().c_str());
		pUnit->SetAttribute("Type", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetType());
		pUnit->SetAttribute("x", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetPosX());
		pUnit->SetAttribute("y", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetPosY());
		pUnit->SetAttribute("Health", (int)(dynamic_cast<CBaseUnit*>( CEntityManager::GetInstance()->m_BaseUnits[i]))->GetHealth());
		pUnit->SetAttribute("Target", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetPosY());
		pUnit->SetAttribute("VelX", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetVelX());
		pUnit->SetAttribute("VelY", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetVelY());
		pUnit->SetAttribute("Team", (int)CEntityManager::GetInstance()->m_BaseUnits[i]->GetTeam());
		pRoot->LinkEndChild(pUnit);
	}

	string out = "SaveSlot";
	ostringstream slotnum;
	slotnum << slot;
	out += slotnum.str();
	out += ".xml";
	doc.SaveFile(out.c_str());
}


void CSaveSystem::LoadSlot(int slot)
{
	CEntityManager::GetInstance()->Clear();

	TiXmlDocument doc;

	string in = "SaveSlot";
	ostringstream slotnum;
	slotnum << slot;
	in += slotnum.str();
	in += ".xml";

	if(doc.LoadFile(in.c_str()) == false)
		return;

	TiXmlElement* pRoot = doc.RootElement();

	int pos = 0;

	TiXmlElement* pTime = pRoot->FirstChildElement("Time");
	pTime->Attribute("time", &pos);
	CSinglePlayerState::GetInstance()->SetTimeCount((float)pos);

	CTeam * team1 = new CTeam(true);
	CTeam * team2 = new CTeam(false);

	CPlayerShip * ship = new CPlayerShip();
	TiXmlElement* pXYPos1 = pRoot->FirstChildElement("Player1");
	pXYPos1->Attribute("x", &pos);
	team1->GetPlayerShip()->SetPosX((float)pos);
	pXYPos1->Attribute("y", &pos);
	team1->GetPlayerShip()->SetPosY((float)pos);
	pXYPos1->Attribute("Health", &pos);
	team1->GetPlayerShip()->SetHealth((float)pos);

	CPlayerShip * ship2 = new CPlayerShip(false, true);
	TiXmlElement* pXYPos2 = pRoot->FirstChildElement("Player2");
	pXYPos2->Attribute("x", &pos);
	team2->GetPlayerShip()->SetPosX((float)pos);
	pXYPos2->Attribute("y", &pos);
	team2->GetPlayerShip()->SetPosY((float)pos);
	pXYPos2->Attribute("Health", &pos);
	team2->GetPlayerShip()->SetHealth((float)pos);
	team2->GetPlayerShip()->SetIsMoving(false);
	team2->GetPlayerShip()->SetAI(true);

	int num;

	TiXmlElement* Tracker = pRoot->FirstChildElement("Barricade");
	Tracker->Attribute("Size", &num);

	for (int i = 0; i < num; i++)
	{
		stringstream word;
		word << "Barricade" << i; 
		TiXmlElement* pElement = pRoot->FirstChildElement(word.str().c_str());
		int info;
		
		pElement->Attribute("Team", &info);
		CBarricade * barricade;

		if(info == 1)
			barricade = new CBarricade(true);
		
		else
			barricade = new CBarricade(false);

		pElement->Attribute("x", &info);
		barricade->SetPosX((float)info);

		pElement->Attribute("y", &info);
		barricade->SetPosY((float)info);
		
		pElement->Attribute("Health", &info);
		barricade->SetHealth((float)info);

		CEntityManager::GetInstance()->AddEntity(barricade);
	}

	Tracker = pRoot->FirstChildElement("Base");
	Tracker->Attribute("Size", &num);

	for (int i = 0; i < num; i++)
	{
		stringstream word;
		word << "Base" << i; 
		TiXmlElement* pElement = pRoot->FirstChildElement(word.str().c_str());
		int info;
		CBase* Base;

		pElement->Attribute("Team", &info);
		if(info == 1)
			Base = new CBase(true);
		else
			Base = new CBase(false);

		pElement->Attribute("x", &info);
		Base->SetPosX((float)info);

		pElement->Attribute("y", &info);
		Base->SetPosY((float)info);

		pElement->Attribute("Health", &info);
		Base->SetHealth((float)info);

		if(Base->GetTeam() == 1)
			team1->SetBase(Base);
		else
			team2->SetBase(Base);
	}

	Tracker = pRoot->FirstChildElement("Crate");
	Tracker->Attribute("Size", &num);

	for (int i = 0; i < num; i++)
	{
		stringstream word;
		word << "Crate" << i; 
		TiXmlElement* pElement = pRoot->FirstChildElement(word.str().c_str());
		int info;
		CCrate* Crate = new CCrate();

		pElement->Attribute("x", &info);
		Crate->SetPosX((float)info);

		pElement->Attribute("y", &info);
		Crate->SetPosY((float)info);

		CEntityManager::GetInstance()->AddEntity(Crate);

	}

	Tracker = pRoot->FirstChildElement("Unit");
	Tracker->Attribute("Size", &num);

	for (int i = 0; i < num; i++)
	{
		stringstream word;
		word << "Unit" << i; 
		TiXmlElement* pElement = pRoot->FirstChildElement(word.str().c_str());
		int info;
		

		pElement->Attribute("Team", &info);
		
		if(info == SHOOT)
		{
			CShooter * shooter = new CShooter();
					
			pElement->Attribute("x", &info);
			shooter->SetPosX((float)info);

			pElement->Attribute("y", &info);
			shooter->SetPosY((float)info);

			pElement->Attribute("Health", &info);
			shooter->SetHealth((float)info);

			pElement->Attribute("Target", &info);
			shooter->SetTarget(CEntityManager::GetInstance()->m_BaseUnits[info]);

			pElement->Attribute("VelX", &info);
			shooter->SetVelX((float)info);

			pElement->Attribute("VelY", &info);
			shooter->SetVelY((float)info);

			pElement->Attribute("Team", &info);
			shooter->SetTeam(info);

			CEntityManager::GetInstance()->AddEntity(shooter);
		}

				
		else if(info == ROCKET)
		{
			CRocketeer * rocketeer = new CRocketeer();
					
			pElement->Attribute("x", &info);
			rocketeer->SetPosX((float)info);

			pElement->Attribute("y", &info);
			rocketeer->SetPosY((float)info);

			pElement->Attribute("Health", &info);
			rocketeer->SetHealth((float)info);

			pElement->Attribute("Target", &info);
			rocketeer->SetTarget(CEntityManager::GetInstance()->m_BaseUnits[info]);

			pElement->Attribute("VelX", &info);
			rocketeer->SetVelX((float)info);

			pElement->Attribute("VelY", &info);
			rocketeer->SetVelY((float)info);

			pElement->Attribute("Team", &info);
			rocketeer->SetTeam(info);

			CEntityManager::GetInstance()->AddEntity(rocketeer);
		}

		else if(info == SHIELD)
		{
			CShielder * shielder = new CShielder();
					
			pElement->Attribute("x", &info);
			shielder->SetPosX((float)info);

			pElement->Attribute("y", &info);
			shielder->SetPosY((float)info);

			pElement->Attribute("Health", &info);
			shielder->SetHealth((float)info);

			pElement->Attribute("Target", &info);
			shielder->SetTarget(CEntityManager::GetInstance()->m_BaseUnits[info]);

			pElement->Attribute("VelX", &info);
			shielder->SetVelX((float)info);

			pElement->Attribute("VelY", &info);
			shielder->SetVelY((float)info);

			pElement->Attribute("Team", &info);
			shielder->SetTeam(info);

			CEntityManager::GetInstance()->AddEntity(shielder);
		}

		else if(info == MECH)
		{
			CMech * mech = new CMech();
					
			pElement->Attribute("x", &info);
			mech->SetPosX((float)info);

			pElement->Attribute("y", &info);
			mech->SetPosY((float)info);

			pElement->Attribute("Health", &info);
			mech->SetHealth((float)info);

			pElement->Attribute("Target", &info);
			mech->SetTarget(CEntityManager::GetInstance()->m_BaseUnits[info]);

			pElement->Attribute("VelX", &info);
			mech->SetVelX((float)info);

			pElement->Attribute("VelY", &info);
			mech->SetVelY((float)info);

			pElement->Attribute("Team", &info);
			mech->SetTeam(info);

			CEntityManager::GetInstance()->AddEntity(mech);
		}

		else if(info == HELI)
		{
			CHelicopter * Heli = new CHelicopter();
					
			pElement->Attribute("x", &info);
			Heli->SetPosX((float)info);

			pElement->Attribute("y", &info);
			Heli->SetPosY((float)info);

			pElement->Attribute("Health", &info);
			Heli->SetHealth((float)info);

			pElement->Attribute("Target", &info);
			Heli->SetTarget(CEntityManager::GetInstance()->m_BaseUnits[info]);

			pElement->Attribute("VelX", &info);
			Heli->SetVelX((float)info);

			pElement->Attribute("VelY", &info);
			Heli->SetVelY((float)info);

			pElement->Attribute("Team", &info);
			Heli->SetTeam(info);

			CEntityManager::GetInstance()->AddEntity(Heli);
		}	

	}
	CLevelManager::GetInstance()->GetCurrLevel()->SetTeam1(team1);
	CLevelManager::GetInstance()->GetCurrLevel()->SetTeam2(team2);
}